<?php
/*
 * Copyright (c) 2021.  Liuhongbin All rights reserved.
 * @domain http://dkyx.cc
 * @author liuhongbin <514660094@qq.com>
 */

namespace app\common\services;

use Exception;
use think\facade\Config;
use think\facade\Db;
use think\facade\Log;

/**
 * Class Addons
 * @package app\common\services
 * User: liuhongbin
 * Date: 2021-05-24 23:01
 */
class Addons
{
    /**
     * @var \think\App
     */
    public $app;
    //数据库前缀
    public $prefix;

    public function __construct()
    {
        $this->app = app();
        $this->prefix = Config::get('database.connections.mysql.prefix');
    }

    /**
     * 获取应用目录
     * @param string $name
     * @return string
     */
    public function getAddonsPath($name = '')
    {
        $path = $this->app->getRootPath() . 'addons/';
        if ($name) {
            $path = $path . $name . "/";
        }
        return $path;
    }

    /**
     * 获取应用公共资源目录
     * @param string $name
     * @return string
     */
    public function getAddonsPublicPath($name = '')
    {
        $path = $this->app->getRootPath() . "public/assets/addons/";
        if ($name) {
            $path = $path . "$name" . "/";

        }
        return $path;
    }

    /**
     * 获取模块前端资源地址
     * @param $name
     * @return string
     */
    public function getAddonsAssetsUrl($name)
    {
        $host = request()->server('HTTP_HOST');
        $url = "//" . $host . "/assets/addons/" . $name . '/';
        return $url;
    }


    /**
     * 安装
     * @param $name
     * @return bool|string
     * @throws Exception
     */
    public function install($name)
    {
        // 获取应用信息
        $info = get_addons_info($name);
        if (!$info) {
            return "应用不存在，或者应用Plugin.php文件不正确";
        }
        // 检查应用文件是否完整
        $config = get_addons_config($name);
        if (!$config) {
            return "应用配置文件config.php不正确";
        }
        // 复制目录
        $source_assets_dir = $this->getAddonsPath($name) . "assets";
        $dest_assets_dir = $this->getAddonsPublicPath($name);
        if (is_dir($source_assets_dir)) {
            copy_dirs($source_assets_dir, $dest_assets_dir);
        }
        // 执行应用install方法
        try {
            $instance = get_addons_instance($name);
            if ($instance !== null) {
                $instance->install();
            }
        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
        //引入独立升级文件
        $file = $this->getAddonsPath($name) . "install.php";
        if (is_file($file)) require_once $file;
        // 执行sql文件
        $this->importSql($name);
        return true;
    }

    public function upgrade($name)
    {
        // 获取应用信息
        $info = get_addons_info($name);
        if (!$info) {
            return "应用不存在，或者应用Plugin.php文件不正确";
        }
        // 检查应用文件是否完整
        $config = get_addons_config($name);
        if (!$config) {
            return "应用配置文件config.php不正确";
        }
        // 复制目录
        $source_assets_dir = $this->getAddonsPath($name) . "assets";
        $dest_assets_dir = $this->getAddonsPublicPath($name);
        if (is_dir($source_assets_dir)) {
            copy_dirs($source_assets_dir, $dest_assets_dir);
        }

        // 执行应用upgrade方法
        try {
            $instance = get_addons_instance($name);
            if ($instance !== null) {
                $instance->upgrade();
            }
        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
        //引入独立升级文件
        $file = $this->getAddonsPath($name) . "upgrade.php";
        if (is_file($file)) require_once $file;
        // 执行sql文件
        $this->importSql($name, "upgrade.sql");
        return true;
    }

    /**
     * 导入SQL
     * @param string $name 插件名称
     * @return  boolean
     */
    public function importSql($name, $sql = 'install.sql')
    {
        $sqlFile = $this->getAddonsPath($name) . $sql;
        if (is_file($sqlFile)) {
            $lines = file($sqlFile);
            $this->batchSql($lines);
        }
        return true;
    }

    /**
     * 批量执行sql
     * @param $lines
     */
    public function batchSql($lines)
    {
        $templine = '';
        if (!is_array($lines)) {
            $lines = explode("\r\n", $lines);
        }
        foreach ($lines as $line) {
            if (substr($line, 0, 2) == '--' || $line == '' || substr($line, 0, 2) == '/*')
                continue;
            $templine .= $line;
            if (substr(trim($line), -1, 1) == ';') {
                $templine = str_ireplace('__PREFIX__', $this->prefix, $templine);
                $templine = str_ireplace('INSERT INTO ', 'INSERT IGNORE INTO ', $templine);
                try {
                    Db::execute($templine);
                } catch (\Exception $e) {
                    //Log::write($e->getMessage());
                }
                $templine = '';
            }
        }
    }

    /**
     * 卸载
     * @param $name
     */
    public function uninstall($name)
    {
        //移除前端文件
        $dest_assets_dir = $this->getAddonsPublicPath($name);
        if (is_dir($dest_assets_dir)) {
            rm_dirs($dest_assets_dir);
        }
        try {
            //执行卸载函数
            $instance = get_addons_instance($name);
            if ($instance !== null) {
                $instance->uninstall();
            }
        } catch (Exception $e) {
            throw new Exception($e->getMessage());
        }
        //引入独立升级文件
        $file = $this->getAddonsPath($name) . "uninstall.php";
        if (is_file($file)) require_once $file;
        return true;
    }

    /**
     * 删除数据表
     * @param $table_name
     * @param bool $prefix
     * @return mixed
     */
    public function dropTable($table_name, $prefix = true)
    {
        if ($prefix) {
            $table_name = $this->prefix . $table_name;
        }
        $sql = "DROP TABLE IF EXISTS " . $table_name . ";";
        return Db::execute($sql);
    }

    /**
     * 获取以应用name为键值的权限数组
     * name=>[
     *     'key'=>'title'
     * ]
     * @param $names
     * @return array
     */
    public function getAuthKeyNameByAddonNames($names)
    {
        $res = [];
        foreach ($names as $key => $name) {
            $auth = get_addons_config($name)['auth'];
            $res[$name] = $this->getAuthKeyNameByAuth($auth);
        }
        return $res;
    }

    /**
     * 将多维权限数组改为一维数组
     * @param $auth
     * @return array
     */
    public function getAuthKeyNameByAuth($auth)
    {
        $res = [];

        foreach ($auth as $key => $value) {

            if (is_array($value)) {
                if (isset($value['title']) && isset($value['value'])) {
                    $res[$key] = $value['title'];
                    $res = array_merge(
                        $res,
                        $this->getAuthKeyNameByAuth($value['value'])
                    );
                } else {
                    continue;
                }
            } else {
                $res[$key] = $value;
            }
        }
        return $res;
    }
}